package christ.mmd.ui;

import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.xml.sax.InputSource;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;

import christ.mmd.DataProvider;
import christ.mmd.R;
import christ.mmd.bl.Community;
import christ.mmd.bl.Event;
import christ.mmd.bl.Fast;
import christ.mmd.bl.FileUpdateInfo;
import christ.mmd.bl.Holiday;
import christ.mmd.bl.reading.Reading;
import christ.mmd.xml.CommunitiesXmlParser;
import christ.mmd.xml.EventsXmlParser;
import christ.mmd.xml.FastXmlParser;
import christ.mmd.xml.FilesUpdateInfoXmlParser;
import christ.mmd.xml.HolidaysXmlParser;
import christ.mmd.xml.ReadingsXmlParser;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class DashboardActivity extends Activity {

	/**
	 * Simple Dialog used to show the splash screen
	 */
	protected Dialog mSplashDialog;
	DataProvider data;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		data = (DataProvider) getLastNonConfigurationInstance();
		if (data != null) {
			// Show splash screen if still loading
			if (data.showSplashScreen) {
				showSplashScreen();
			}
			setContentView(R.layout.dashboard);

			// Rebuild your UI with your saved state here
		} else {
			data = new DataProvider();
			showSplashScreen();
			setContentView(R.layout.dashboard);
			// Do your heavy loading here on a background thread
		}

		Button communitiesBtn = (Button) findViewById(R.id.mBtnWho);
		communitiesBtn.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				Intent i = new Intent(DashboardActivity.this,
						CommunityListActivity.class);
				i.putExtra("DATA_PROVIDER", data);
				startActivity(i);
			}
		});
		
		Button regionsBtn = (Button) findViewById(R.id.mBtnWhere);
		regionsBtn.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				Intent i = new Intent(DashboardActivity.this,
						RegionMapActivity.class);
				i.putExtra("DATA_PROVIDER", data);
				startActivity(i);
			}
		});


	}

	@Override
	public Object onRetainNonConfigurationInstance() {
		// Save your important data here
		if (data == null) {
			data = new DataProvider();
		}

		if (mSplashDialog != null) {
			data.showSplashScreen = true;
			removeSplashScreen();
		}
		return data;
	}

	/**
	 * Removes the Dialog that displays the splash screen
	 */
	protected void removeSplashScreen() {
		if (mSplashDialog != null) {
			mSplashDialog.dismiss();
			mSplashDialog = null;
		}
	}

	/**
	 * Shows the splash screen over the full Activity
	 */
	protected void showSplashScreen() {
		mSplashDialog = new Dialog(this, R.style.SplashScreen);
		mSplashDialog.setContentView(R.layout.splashscreen);
		mSplashDialog.setCancelable(false);
		mSplashDialog.show();

		// Set Runnable to remove splash screen just in case
		final Handler handler = new Handler();
		handler.postAtFrontOfQueue(new Runnable() {
			@Override
			public void run() {
				new DownloadAndProcessXmlDataTask().execute(data);
			}
		});
	}

	// Implementation of AsyncTask used to download XML feed from
	// stackoverflow.com.
	private class DownloadAndProcessXmlDataTask extends
			AsyncTask<DataProvider, Void, DataProvider> {
		@Override
		protected DataProvider doInBackground(DataProvider... voids) {
			DataProvider result = voids[0];
			try {
				List<FileUpdateInfo> fileUpdateInfoList = loadAndProcessXmlFileUpdateInfo("http://dl.dropbox.com/u/10342089/Catalog/MakeMyDay/updates.xml");
				for (FileUpdateInfo fileUpdateInfo : fileUpdateInfoList) {
					if (result.isFileUpdateInfoNewer(fileUpdateInfo)) {
						// download, parse and update data
						switch (fileUpdateInfo.getType()) {
						case communities:
							List<Community> communities = loadAndProcessXmlCommunities(fileUpdateInfo
									.getLink());
							result.updateCommunities(communities);
							break;
						case readings:
							List<Reading> readings = loadAndProcessXmlReadings(fileUpdateInfo
									.getLink());
							result.updateReadings(readings);
							break;
						case holidays:
							List<Holiday> holidays = loadAndProcessXmlHolidays(fileUpdateInfo
									.getLink());
							result.updateHolidays(holidays);
							break;
						case events:
							List<Event> events = loadAndProcessXmlEvents(fileUpdateInfo
									.getLink());
							result.updateEvents(events);
							break;
						case fasts:
							List<Fast> fasts = loadAndProcessXmlFast(fileUpdateInfo
									.getLink());
							result.updateFasts(fasts);
							break;
						default:
							break;
						}
						// update fileUpdateInfo
						result.updateFileUpdateInfo(fileUpdateInfo);
					}
				}

			} catch (IOException e) {
				AlertDialog.Builder dialog = new AlertDialog.Builder(
						DashboardActivity.this);
				dialog.setTitle("Attention");
				dialog.setMessage(e.toString());
				// getResources().getString(R.string.connection_error);
			} catch (XmlPullParserException e) {
				AlertDialog.Builder dialog = new AlertDialog.Builder(
						DashboardActivity.this);
				dialog.setTitle("Attention");
				dialog.setMessage(e.toString());
				// getResources().getString(R.string.xml_error);
			}
			return result;
		}

		@Override
		protected void onPostExecute(DataProvider result) {
			removeSplashScreen();
		}
	}

	private List<Fast> loadAndProcessXmlFast(String urlString)
			throws XmlPullParserException, IOException {
		InputStream stream = null;
		// Instantiate the parser
		FastXmlParser stackOverflowXmlParser = new FastXmlParser();
		List<Fast> entries = null;

		try {
			stream = downloadUrl(urlString);
			entries = stackOverflowXmlParser.parse(stream);
			// Makes sure that the InputStream is closed after the app is
			// finished using it.
		} finally {
			if (stream != null) {
				stream.close();
			}
		}
		return entries;
	}

	private List<Event> loadAndProcessXmlEvents(String urlString)
			throws XmlPullParserException, IOException {
		InputStream stream = null;
		// Instantiate the parser
		EventsXmlParser stackOverflowXmlParser = new EventsXmlParser();
		List<Event> entries = null;

		try {
			stream = downloadUrl(urlString);
			entries = stackOverflowXmlParser.parse(stream);
			// Makes sure that the InputStream is closed after the app is
			// finished using it.
		} finally {
			if (stream != null) {
				stream.close();
			}
		}
		return entries;
	}

	private List<Holiday> loadAndProcessXmlHolidays(String urlString)
			throws XmlPullParserException, IOException {
		InputStream stream = null;
		// Instantiate the parser
		HolidaysXmlParser stackOverflowXmlParser = new HolidaysXmlParser();
		List<Holiday> entries = null;

		try {
			stream = downloadUrl(urlString);
			entries = stackOverflowXmlParser.parse(stream);
			// Makes sure that the InputStream is closed after the app is
			// finished using it.
		} finally {
			if (stream != null) {
				stream.close();
			}
		}
		return entries;
	}

	private List<Reading> loadAndProcessXmlReadings(String urlString)
			throws XmlPullParserException, IOException {
		InputStream stream = null;
		// Instantiate the parser
		ReadingsXmlParser stackOverflowXmlParser = new ReadingsXmlParser();
		List<Reading> entries = null;

		try {
			stream = downloadUrl(urlString);
			entries = stackOverflowXmlParser.parse(stream);
			// Makes sure that the InputStream is closed after the app is
			// finished using it.
		} finally {
			if (stream != null) {
				stream.close();
			}
		}
		return entries;
	}

	private List<Community> loadAndProcessXmlCommunities(String urlString)
			throws XmlPullParserException, IOException {
		InputStream stream = null;
		// Instantiate the parser
		CommunitiesXmlParser stackOverflowXmlParser = new CommunitiesXmlParser();
		List<Community> entries = null;

		try {
			stream = downloadUrl(urlString);
			entries = stackOverflowXmlParser.parse(stream);
			// Makes sure that the InputStream is closed after the app is
			// finished using it.
		} finally {
			if (stream != null) {
				stream.close();
			}
		}
		return entries;
	}

	private List<FileUpdateInfo> loadAndProcessXmlFileUpdateInfo(
			String urlString) throws XmlPullParserException, IOException {
		InputStream stream = null;
		// Instantiate the parser
		FilesUpdateInfoXmlParser stackOverflowXmlParser = new FilesUpdateInfoXmlParser();
		List<FileUpdateInfo> entries = null;

		try {
			stream = downloadUrl(urlString);
			entries = stackOverflowXmlParser.parse(stream);
			// Makes sure that the InputStream is closed after the app is
			// finished using it.
		} finally {
			if (stream != null) {
				stream.close();
			}
		}
		return entries;
	}

	// Given a string representation of a URL, sets up a connection and gets
	// an input stream.
	private InputStream downloadUrl(String urlString) throws IOException {
		URL url = new URL(urlString);
		HttpURLConnection conn = (HttpURLConnection) url.openConnection();
		conn.setReadTimeout(10000 /* milliseconds */);
		conn.setConnectTimeout(15000 /* milliseconds */);
		conn.setRequestMethod("GET");
		conn.setDoInput(true);
		// Starts the query
		conn.connect();
		InputStream stream = conn.getInputStream();
		return stream;
	}
}